Thailand Trade dependency

Trade dependency play an important role of country’s economic development and stability, since it is vulnerable to external shocks such as economic recessions in trading partners, volatile global commodty prices, and disruptions in supply chains, potentially leading to job losses, price fluctuations, and instability, if the country relies heavily on a narrow ranges of exports and import sources. Thailand is export-dependence country for a long time. In this analysis, I will deep dive into Thailand trade dependency compared to other countries.

# Install package and call library 'WDI' and Import data
if (!require("WDI")) install.packages("WDI")
## Loading required package: WDI
if (!require("ggplot2")) install.packages("ggplot2")
## Loading required package: ggplot2
if (!require("dplyr")) install.packages("dplyr")
## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
if (!require("tidyverse")) install.packages("tidyverse")
## Loading required package: tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ lubridate 1.9.4     ✔ tibble    3.2.1
## ✔ purrr     1.0.2     ✔ tidyr     1.3.1
## ✔ readr     2.1.5     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
if (!require("rnaturalearth")) install.packages("rnaturalearthdata")
## Loading required package: rnaturalearth
if (!require("sf")) install.packages("sf") 
## Loading required package: sf
## Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
library(tidyverse)
library(plotly)
## 
## Attaching package: 'plotly'
## 
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## 
## The following object is masked from 'package:stats':
## 
##     filter
## 
## The following object is masked from 'package:graphics':
## 
##     layout
library(WDI)
library(ggplot2)
library(dplyr)
library(rnaturalearth) # World Map Data from Natural Earth 
library(sf) # Geographic Simple Features in R 
library(forcats) 
# import trade data
trade_data <- WDI(indicator=c("NY.GDP.PCAP.KD","NE.TRD.GNFS.ZS","NY.GDP.MKTP.KD","NE.EXP.GNFS.KD","NE.IMP.GNFS.KD"),extra=TRUE)

# chnage name into the easy name 
names(trade_data)[names(trade_data)=='NY.GDP.PCAP.KD'] <- 'gdp_percap'
names(trade_data)[names(trade_data)=='NE.TRD.GNFS.ZS'] <- 'trade_dep'
names(trade_data)[names(trade_data)=='NY.GDP.MKTP.KD'] <- 'gdp'
names(trade_data)[names(trade_data)=='NE.EXP.GNFS.KD'] <- 'export'
names(trade_data)[names(trade_data)=='NE.IMP.GNFS.KD'] <- 'import'

trade_data <- trade_data %>%
  mutate(net_trade_balance = export - import)  # Compute net trade balance

#check heading and summarize of the data
head(trade_data)
##       country iso2c iso3c year status lastupdated gdp_percap trade_dep gdp
## 1 Afghanistan    AF   AFG 1961         2025-01-28         NA        NA  NA
## 2 Afghanistan    AF   AFG 1974         2025-01-28         NA        NA  NA
## 3 Afghanistan    AF   AFG 1962         2025-01-28         NA        NA  NA
## 4 Afghanistan    AF   AFG 1963         2025-01-28         NA        NA  NA
## 5 Afghanistan    AF   AFG 1973         2025-01-28         NA        NA  NA
## 6 Afghanistan    AF   AFG 1989         2025-01-28         NA        NA  NA
##   export import     region capital longitude latitude     income lending
## 1     NA     NA South Asia   Kabul   69.1761  34.5228 Low income     IDA
## 2     NA     NA South Asia   Kabul   69.1761  34.5228 Low income     IDA
## 3     NA     NA South Asia   Kabul   69.1761  34.5228 Low income     IDA
## 4     NA     NA South Asia   Kabul   69.1761  34.5228 Low income     IDA
## 5     NA     NA South Asia   Kabul   69.1761  34.5228 Low income     IDA
## 6     NA     NA South Asia   Kabul   69.1761  34.5228 Low income     IDA
##   net_trade_balance
## 1                NA
## 2                NA
## 3                NA
## 4                NA
## 5                NA
## 6                NA
summary(trade_data)
##    country             iso2c              iso3c                year     
##  Length:17024       Length:17024       Length:17024       Min.   :1960  
##  Class :character   Class :character   Class :character   1st Qu.:1976  
##  Mode  :character   Mode  :character   Mode  :character   Median :1992  
##                                                           Mean   :1992  
##                                                           3rd Qu.:2007  
##                                                           Max.   :2023  
##                                                                         
##     status          lastupdated          gdp_percap       trade_dep      
##  Length:17024       Length:17024       Min.   :     0   Min.   :  0.021  
##  Class :character   Class :character   1st Qu.:  1299   1st Qu.: 41.587  
##  Mode  :character   Mode  :character   Median :  3679   Median : 60.544  
##                                        Mean   : 11205   Mean   : 72.403  
##                                        3rd Qu.: 13066   3rd Qu.: 90.776  
##                                        Max.   :224582   Max.   :863.195  
##                                        NA's   :3016     NA's   :6106     
##       gdp                export              import             region         
##  Min.   :1.249e+03   Min.   :4.651e+05   Min.   :1.156e+06   Length:17024      
##  1st Qu.:5.244e+09   1st Qu.:2.888e+09   1st Qu.:3.699e+09   Class :character  
##  Median :3.441e+10   Median :1.680e+10   Median :1.801e+10   Mode  :character  
##  Mean   :1.526e+12   Mean   :4.019e+11   Mean   :4.140e+11                     
##  3rd Qu.:3.624e+11   3rd Qu.:1.431e+11   3rd Qu.:1.488e+11                     
##  Max.   :9.335e+13   Max.   :2.619e+13   Max.   :2.615e+13                     
##  NA's   :3021        NA's   :8456        NA's   :8431                          
##    capital           longitude           latitude            income         
##  Length:17024       Length:17024       Length:17024       Length:17024      
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##    lending          net_trade_balance   
##  Length:17024       Min.   :-1.186e+12  
##  Class :character   1st Qu.:-3.611e+09  
##  Mode  :character   Median :-2.990e+08  
##                     Mean   : 4.319e+06  
##                     3rd Qu.: 3.107e+09  
##                     Max.   : 7.907e+11  
##                     NA's   :8471
# Filter data for 2023 and compute the variables
trade_data_2023 <- trade_data %>%
  filter(year == 2023) %>%
  mutate(
    log_gdp_percap    = log(gdp_percap),
    net_trade_balance = log(abs(export - import)) * sign(export - import)
  )

# Create the interactive Plotly plot
fig <- plot_ly(
  data = trade_data_2023,
  x = ~log_gdp_percap,
  y = ~trade_dep,
  type = 'scatter',
  mode = 'markers+text',
  text = ~iso3c,
  textposition = 'top center',
  marker = list(
    opacity = 0.5,
    color = ~net_trade_balance,
    coloraxis = "coloraxis"
  )
) %>%
  layout(
    title = "Trade Dependency and GDP Per Capita, 2023",
    xaxis = list(title = "Log of GDP per Capita (2015 USD)"),
    yaxis = list(title = "Trade Dependency (% of GDP)"),
    coloraxis = list(
      colorscale = list(
        c(0, "darkorange"),  # High net imports (deficit)
        c(0.5, "black"),     # Balanced trade
        c(1, "darkblue")     # High net exports (surplus)
      ),
      colorbar = list(
        title = list(text = "Log of Net Export<br>(Exports - Imports)")
      )
    ),
    template = "plotly_white"
  )

fig
## Warning: Ignoring 66 observations
trade_data_anim <- trade_data %>%
  filter(gdp_percap > 0, 
         !is.na(gdp_percap), 
         !is.na(trade_dep), 
         !is.na(export), 
         !is.na(import)) %>%
  mutate(
    log_gdp_percap    = log(gdp_percap),
    net_trade_balance = log(abs(export - import)) * sign(export - import)
  )

thailand_data <- trade_data_anim %>% filter(country == "Thailand")
others_data   <- trade_data_anim %>% filter(country != "Thailand")


custom_text <- ~paste(
  country,year,
  "<br>GDP per Capita (2015 USD): ", round(gdp_percap, 2),
  "<br>Trade Dependency (%): ", round(trade_dep, 2),
  "<br>Net Exports (Billions): ", round((export - import)/10000000, 2)
)

fig <- plot_ly() %>%
  add_trace(
    data = others_data,
    x = ~log_gdp_percap,
    y = ~trade_dep,
    frame = ~year,  
    text = custom_text,
    type = 'scatter',
    mode = 'markers',
    marker = list(size = 10, opacity = 0.8, color = "lightgray"),
    showlegend = FALSE
  ) %>%
  add_trace(
    data = thailand_data,
    x = ~log_gdp_percap,
    y = ~trade_dep,
    frame = ~year,
    type = 'scatter',
    mode = 'markers+text',
    text = custom_text, 
    textfont = list(      
      family = "Times",
      size = 14
    ),
    textposition = 'top center',
    marker = list(
      size = 12,
      opacity = 1,
      showscale = FALSE
    ),
    color = ~net_trade_balance,
    showlegend = FALSE
  ) %>%
  layout(
  title = list(
    text = "\nThailand Trade Dependency and GDP Per Capita, 1960-2023",
    x = 0.15,               
    xanchor = "left",
    font = list(
      family = "Times",
      fontface="bold",
      size = 18,
      color = "black"
    )
  ),
    xaxis = list(
      title = list(
        text = "Log of GDP per Capita (2015 USD)",
        font = list(
          family = "Times",
          size = 14,
          color = "black"
        )
      ),
      showgrid = FALSE   # Drop x-axis grid lines
    ),
    yaxis = list(
      title = list(
        text = "Trade Dependency (% of GDP)",
        font = list(
          family = "Times",
          size = 14,
          color = "black"
        )
      ),
      range = c(0, 500),
      showgrid = FALSE   # Drop y-axis grid lines
    ),
  coloraxis = list(
    colorscale = list(
      c(-20, "darkorange"),  
      c(0, "black"),     
      c(20, "darkblue")   
    ),
    colorbar = list(
      title = list(
        text = "Log of Net Export<br>(Exports - Imports)",
        font = list(
          family = "Times",
          size = 12,
          color = "black"
        )
      ),
      font = list(
        family = "Times",
        size = 12,
        color = "black"
      )
    )
  ),
  template = "plotly_white"
) %>%
  animation_opts(
    frame = 450,       
    transition = 0,
    redraw = TRUE
  ) %>%
  animation_slider(
    currentvalue = list(prefix = "Year: ")
  )

years <- sort(unique(thailand_data$year))
annotations_list <- list()

if (!is.null(fig$x$frames)) {
  for (i in seq_along(fig$x$frames)) {
    frame_year <- fig$x$frames[[i]]$name
    if (frame_year %in% names(annotations_list)) {
      fig$x$frames[[i]]$layout <- list(annotations = list(annotations_list[[frame_year]]))
    }
  }
}

fig
df <- trade_data %>%
  filter(year %in% c(1960, 2023), !is.na(trade_dep), !is.na(income), income != "Aggregates")   %>%
  group_by(country) %>%
  filter(n() == 2) %>%  
  ungroup() %>%
  arrange(country, year) %>%
  mutate(
    paired = as.numeric(factor(country)),  
    year = factor(year),                   
    trade_dep = as.numeric(trade_dep),    
    income = factor(income, levels = c("High income", "Upper middle income", "Lower middle income", "Low income"))
  )
year_colors <- c("1960" = "lightblue", "2023" = "darkblue")

p <- ggplot(df, aes(x = trade_dep, y = fct_reorder(country, trade_dep, .na_rm = TRUE))) +
  geom_line(aes(group = paired), color = "lightblue") +  
  geom_point(aes(color = year), size = 2) +       
  scale_color_manual(name = "Year", values = year_colors) + 
  labs(
    x = "Trade Dependency (% of GDP)",
    y = "Country",
    title = "Trade Dependency Change by Income Group (1960 vs. 2023)"
  ) +
  theme_minimal() + 
  theme(text = element_text(size = 10)) +
  facet_wrap(~income, ncol = 1, scales = "free_y")  


ggplotly(p, height = 800)
world <- ne_countries(scale = "medium", returnclass = "sf") %>%
  filter(admin != "Antarctica")

target_crs <- "+proj=moll"
world_moll <- st_transform(world, crs = target_crs)

world_trade <- world_moll %>%
  left_join(trade_data_2023, by = c("iso_a3" = "iso3c"))

world_trade_df <- world_trade %>%
  st_drop_geometry()  

trade_map <- plot_ly(
  data = world_trade_df,
  type = "choropleth",
  locations = ~iso_a3,
  z = ~trade_dep,
  text = ~paste(admin, "<br>Trade Dependency:", round(trade_dep, 2), "%"),
  colorscale = "Viridis",
  colorbar = list(title = "Trade Dependency (%)"),  # Add title to color bar
  marker = list(line = list(color = "black", width = 0.5))
) %>%
  layout(
    title = "Trade Dependency by Country (2023)",
    geo = list(
      projection = list(type = "mollweide"),
      showcoastlines = TRUE,
      coastlinecolor = "black"
    )
  )

trade_map
## Warning: Ignoring 86 observations
thailand_trade <- trade_data %>%
  arrange(year) %>%
  filter(country == "Thailand", year >= 1960, year <= 2023) %>%
  select(year, export, import, gdp)  

fig <- plot_ly(data = thailand_trade) %>%
  add_lines(x = ~year, y = ~export, name = "Exports", line = list(color = "darkblue")) %>%
  add_lines(x = ~year, y = ~import, name = "Imports", line = list(color = "darkorange")) %>%
  # add_lines(x = ~year, y = ~gdp, name = "GDP", line = list(color = "grey")) %>%
  layout(
    title = "Thailand’s Export and Import (1960-2023)",
    xaxis = list(title = "Year"),
    yaxis = list(title = "Trade Value (in USD)"),
    legend = list(x = 0.1, y = 0.9),
    hovermode = "x unified"
  )

fig
thailand_trade <- trade_data %>%
  filter(country == "Thailand", year >= 1960, year <= 2023) %>%
  select(year, export, import) %>%
  arrange(year) %>%
  mutate(
    net_export = export - import
  )

fig <- plot_ly(data = thailand_trade) %>%
  add_trace(
    x = ~year, y = ~import, name = "Imports", type = "scatter", mode = "none",
    fill = "tozeroy", fillcolor = "rgba(255, 140, 0, 0.5)"  
  ) %>%
  add_trace(
    x = ~year, y = ~export, name = "Exports", type = "scatter", mode = "none",
    fill = "tozeroy", fillcolor = "rgba(0, 0, 139, 0.5)" 
  ) %>%
  add_trace(
    x = ~year, y = ~net_export, name = "Net Exports", type = "scatter", mode = "lines",
    line = list(color = "black", width = 2, dash = "solid")  
  ) %>%
  layout(
    title = "Thailand’s Export, Import & Net Export (1960-2023)",
    xaxis = list(
      title = "Year",
      showgrid = FALSE  
    ),
    yaxis = list(
      title = "Trade Value (in USD)",
      zeroline = TRUE, zerolinecolor = "black",
      showgrid = FALSE  
    ),
    legend = list(x = 0.1, y = 0.9),
    hovermode = "x unified",

    shapes = list(
      list(
        type = "line",
        x0 = 1997, x1 = 1997,  
        y0 = min(thailand_trade$import), y1 = max(thailand_trade$export),  
        xref = "x", yref = "y",
        line = list(color = "black", width = 2, dash = "dot")  
      )
    ),

    annotations = list(
      list(
        x = 1997, y = max(thailand_trade$export) * 0.8,  
        text = "<b>Asian Financial Crisis 1997</b><br>Sharp decline in import",
        showarrow = TRUE,
        arrowhead = 3,  
        arrowsize = 1,
        ax = 50, ay = -40,  # Arrow position
        bgcolor = "rgba(255, 255, 255, 1)",  
        bordercolor = "black",  # Box border
        font = list(size = 12, color = "black")
      )
    )
  )

fig
thailand_trade <- thailand_trade %>%
  arrange(year) %>%
  mutate(
    export_growth = (export / lag(export) - 1) * 100,  
    import_growth = (import / lag(import) - 1) * 100   
  ) %>%
  filter(!is.na(export_growth) & !is.na(import_growth))  


fig <- plot_ly(data = thailand_trade) %>%
  add_lines(x = ~year, y = ~export_growth, name = "Export Growth (%)", line = list(color = "darkblue")) %>%
  add_lines(x = ~year, y = ~import_growth, name = "Import Growth (%)", line = list(color = "darkorange")) %>%
  layout(
    title = "Thailand’s Export and Import Growth Rate (1960-2023)",
    xaxis = list(title = "Year"),
    yaxis = list(title = "Growth Rate (%)"),
    legend = list(x = 0.1, y = 0.9),
    hovermode = "x unified"
  )

fig